#!/usr/bin/python3
# %%
import sys
import os
import cloudmusic
import re

# %%
_default_profile = {
    "playlist": None,
    "latest": None,  # the latest song name downloaded
    "latest_id": None,  # the latest song id downloaded
    "dir": "cloudy-music",
    "songs": [],  # the songs in the playlist
}

_default_profile_name = "cm.profile.json"


def load_profile(fn="profile.json"):
    import json

    if not os.path.exists(fn):
        return _default_profile
    loads = {}
    with open(fn, "r") as f:
        loads = json.load(f)
    profile = _default_profile.copy()
    profile.update(loads)
    return profile


def save_profile(profile, fn="profile.json"):
    import json

    _profile = load_profile(fn)
    update_songs = False
    if "playlist" in profile and profile["playlist"] != _profile["playlist"]:
        update_songs = True
    _profile.update(profile)
    if _profile.get("playlist") and (update_songs or not _profile["songs"]):
        _profile["songs"] = update_songs_from(_profile["playlist"])
    if profile.get("latest"):
        assert profile.get("latest_id")
    if profile.get("latest_id"):
        assert profile.get("latest")
    last_id = profile.get("latest_id")
    if last_id and _profile["songs"] and last_id not in _profile["songs"]:
        _profile["latest"] = None
        _profile["latest_id"] = None
    if not _profile["latest_id"] and _profile["songs"]:
        _profile["latest_id"] = _profile["songs"][0]
        _profile["latest"] = cloudmusic.getMusic(_profile["latest_id"]).name

    with open(fn, "w") as f:
        json.dump(_profile, f, indent=4)


def update_songs_from(playlist_id: str):
    songs = cloudmusic.getPlaylist(playlist_id)
    res = [x.id for x in songs]
    return res


def get_newest_songs(profile, fn):
    if not profile:
        profile = load_profile()
    if not profile["playlist"]:
        return None
    if not profile["songs"]:
        songs = update_songs_from(profile["playlist"])
        save_profile({"songs": songs}, fn)
    else:
        songs = profile["songs"]
    if not profile["latest_id"]:
        # return the first song if not determined
        return [songs[0]]
    last_song = profile["latest_id"]
    new_songs = []
    for song in songs:
        if song == last_song:
            break
        new_songs.append(song)
    new_songs.reverse()
    return new_songs


def update_play_list(playlist, fn):
    songs = update_songs_from(playlist)
    save_profile({"songs": songs}, fn=fn)


def auto_sync_songs(fn="profile.json"):
    profile = load_profile(fn)
    songs = get_newest_songs(profile, fn)
    if not songs:
        return
    for song in songs:
        m = cloudmusic.getMusic(song)
        mp_path = m.download(level="exhigh", dirs=profile["dir"])
        if not mp_path:
            break
        profile["latest"] = m.name
        profile["latest_id"] = m.id
        print(f"Downloaded {mp_path}")
        save_profile(
        {"latest": profile["latest"], "latest_id": profile["latest_id"]}, fn=fn
    )


# %%
if __name__ == "__main__":
    os.chdir(os.path.dirname(os.path.abspath(__file__)))
    music_id = None
    if len(sys.argv) < 2:
        import pyperclip

        music_id = pyperclip.paste()
        if music_id and "id=" not in music_id:
            music_id = None
    elif sys.argv[1] == "-h" or sys.argv[1] == "--help":
        print("Usage: python3 nave.py <music_id>")
        print("    nave.py --set playlist_id")
        print("    nave.py --sync")
        print("    nave.py --sync-playlist")
        sys.exit(0)
    elif sys.argv[1] == "--set":
        if len(sys.argv) < 3:
            print("Usage: python3 nave.py --set playlist_id")
            sys.exit(1)
        profile = {}
        profile["playlist"] = sys.argv[2]
        save_profile(profile, fn=_default_profile_name)
        print(f"Set playlist to {sys.argv[2]}")
        sys.exit(0)
    elif sys.argv[1] == "--sync":
        auto_sync_songs(fn=_default_profile_name)
        sys.exit(0)
    elif sys.argv[1] == "--sync-playlist":
        profile = load_profile(_default_profile_name)
        if not profile["playlist"]:
            print("No playlist set, please run `python3 nave.py --set playlist_id` first")
            sys.exit(1)
        update_play_list(profile["playlist"], fn=_default_profile_name)
        sys.exit(0)
    if not music_id:
        if len(sys.argv) < 2:
            print("Usage: python3 nave.py <music_id>")
            sys.exit(1)
        music_id = sys.argv[1]
    if music_id.__contains__("id="):
        music_id = re.findall(r"id=(\d+)", music_id)[0]
    print(f"[{music_id}]")
    if re.match(r"\d+", music_id):
        m = cloudmusic.getMusic(music_id)
    else:
        ms = cloudmusic.search(music_id)
        if len(ms) == 0:
            print("No music found")
            sys.exit(1)
        print("Search result:")
        for i, m in enumerate(ms):
            print(f"{i + 1}. {m.name} - {m.artist}")
        print("Please choose one music:")
        s = input()
        if not s:
            num = 1
        else:
            num = int(s)
        m = ms[num - 1]
    mp_path = m.download(level="exhigh", dirs=load_profile()["dir"])
    if not mp_path:
        exit(1)
    print(mp_path)
    save_profile({"latest": m.name, "latest_id": m.id}, fn=_default_profile_name)
